﻿Option Explicit On
'=================================================
'  Author:  Daniel.Chan@FoxGlobal
'  Mail:    magichydra@163.com;  Daniel.Chan@foxglobal.com
'  QQ:      39182649
'
'  FileName:      HFMProxy.vb
'  Version:         1.1.0
'  Function List: 
'  History:         
'  <author>  <time>   <version >   <desc>
'=================================================


Imports System.Collections.Generic

Imports HSVSESSIONLib
Imports HSXSERVERLib
Imports HSXCLIENTLib
Imports HSVMETADATALib
Imports HSVSECURITYACCESSLib
Imports HFMWAPPLICATIONSLib
Imports HSVWEBCLIENTLib
Imports HSVJOURNALLOADACVLib
Imports HSVMETADATALOADACVLib
Imports HSVSECURITYLOADACVLib
Imports HFMCONSTANTSLib
Imports HSVCDATALOADLib
Imports HSVSYSTEMINFOLib
Imports HFMWSESSIONLib
Imports HFMWSTARSCHEMALib
Imports HFMWMBRSELLib
Imports HFMwSystemInfoLib
Imports HsvJournalsLib
Imports MSXML2
Imports HsvStarSchemaACMLib





Imports System.IO
Imports System.Text


''' <summary>
''' MetaItem 基础类，用于定义从Hyperion中取到的元数据
''' </summary>
''' <remarks></remarks>
Public Class MetaItem
    ''' <summary>
    ''' 名称
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ShortName As String

    Public Property ParentName As String

    ''' <summary>
    ''' 长名称，主要针对 Entity 维度，格式  Parent.Child
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property FullName As String

    ''' <summary>
    ''' Hyperion HFM 中的描述
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Description As String

    Public Property FullDescription As String

    ''' <summary>
    ''' 属性字段，目前未用到，暂时保留用于扩展
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Attribute As String
End Class

''' <summary>
''' HFM COM组件代理程序, 提供以下接口
''' 
''' TODO 按照下面的划分，将大类拆成不同的子类（参考HFM中分类的原则）
''' 
''' [00 - 公共方法]
''' 
''' Login                    登录 
''' Logout                   退出
''' 
''' ReturnVBCrLf             回车换行
''' SetFileContent           写文件
''' LoadFile                 读文件
''' SplitText                文本拆分
''' WriteToFile              写文件
''' 
''' 
''' [01 - 数据相关操作]
''' 
''' CheckCustom1Validate     检查科目和Custom1的有效性
''' CheckCustom2Validate     检查科目和Custom2的有效性
''' CheckCustom3Validate     检查科目和Custom3的有效性
''' TODO CheckCustom4Validate   检查科目和Custom4的有效性
''' CheckICPValidte          检查科目和ICP的有效性
''' CheckSecurity            权限检查
''' TODO Revise  CheckServurityResult     权限检查并返回结果
''' GetCell                  获取指定单元格数据      
''' GetProcessLevel          获取审核级别
''' NOInputErrMsg            NOINPUT 规则处理
''' Validate                 数据校验 
''' LoadData                 加载数据
''' TODO Revise FormatErrDimension           还原出错的日记帐
''' 
''' 
''' [02 - 扩展分析相关]
''' 
''' GetExtendedAnalyticTemplates    获取扩展分析模板列表
''' CreateStarSchema         执行扩展分析
''' TODO Revise  expandlistIfNecessary    将成员公式转换为成员
''' TODO Revisse CheckStatus              获取扩展分析的状态
''' 
''' 
''' [03 - 日记帐相关]
''' 
''' GetJournalGroup          获取日记帐组信息
''' ExtractJournals          导出日记帐
''' LoadJournals             加载日记帐
''' 
''' 
''' [04 - 权限相关]
''' 
''' ExtractSecurity          导出权限
''' 
''' 
''' [05 - 元数据相关]
''' 
''' TODO Review GetAppname               获取应用名称
''' TODO Review GetUsername              获取用户名
''' TODO Review GetLanguageID            获取语言
''' TODO Review GetLastUpdate            获取上次更新时间
''' ExtractDimensions 　　　　导出元数据
''' TODO Review GetAccountLastUpdate     获取Account上次更新的时间
''' 
''' GetDynamicsmemberList    获取成员 (根据成员列表)
''' GetMemberID              获取成员ID 
''' TODO Review GetMemberList          获取memberList列表
''' TODO Review GetMemberListEx        获取Memm
''' 
''' GetAccounts              获取科目维度
''' GetAccountsEx            获取科目维护 (根据成员列表)　
''' GetEntities              获取Entity维度
''' GetEntitiesDetail        获取Entity维度详细信息　(包括审批状态)
''' GetEntityEx              获取Entity维度 (根据成员列表)
''' GetCustom1               获取Custom1维度 (根据成员列表)
''' GetPeriod                获取Period维度 
''' GetPeriodEx              获取Period维度  (根据成员列表)
''' GetScenario              获取Scenario维度
''' GetScenarioEx            获取Scenario维度  (根据成员列表)
''' TODO Revise GetCustom2LastUpdate     获取Custom2上次更新的时间
''' GetCustom2               获取Custom2维度 (根据成员列表)
''' TODO Revise GetCustom3LastUpdate     获取Custom3上次更新的时间 
''' GetCustom3               获取Custom3维度 (根据成员列表)
''' TODO Add  GetCustom4
''' 
''' </summary>
''' <remarks></remarks>
Public Class HFMProxy
    ''' <summary>
    ''' cClient 代理类
    ''' </summary>
    ''' <remarks></remarks>
    Public cClient As HsxClient

    ''' <summary>
    ''' cWebSession 用户登录后的Session类，依赖于Web Server, Server, Client
    ''' TODO Revise Not to use cWebSession
    ''' </summary>
    ''' <remarks></remarks>
    Public cWebSession As HFMwSession

    ''' <summary>
    ''' cSession 用户登录后的Session类，依赖于Server, Client
    ''' </summary>
    ''' <remarks></remarks>
    Public cSession As HsvSession

    ''' <summary>
    ''' cServer 代理类
    ''' </summary>
    ''' <remarks></remarks>
    Public cServer As HsxServer

    ''' <summary>
    ''' 文件读取公共方法
    ''' TODO  增加典型调用的例子
    ''' </summary>
    ''' <param name="Path">文件全路径</param>
    ''' <param name="Charset">文件编码</param>
    ''' <returns>文本</returns>
    ''' <remarks></remarks>
    Private Function LoadFile(ByVal Path As String, ByVal Charset As String) As String
        Dim oReader = Nothing

        ' TODO 异常没有捕获，是否需要捕获 
        Try
            oReader = New StreamReader(Path, Encoding.GetEncoding(Charset))
            LoadFile = oReader.ReadToEnd()
        Finally
            If Not (oReader Is Nothing) Then
                oReader.Close()
                oReader = Nothing
            End If
        End Try
    End Function

    ''' <summary>
    ''' 写文件
    ''' </summary>
    ''' <param name="sPath">文件全路径</param>
    ''' <param name="Message">写入的文本</param>
    ''' <param name="Charset">文件编码</param>
    ''' <remarks></remarks>
    Private Sub WriteToFile(ByVal sPath As String, ByVal Message As String, ByVal Charset As String)
        Dim oWriter = Nothing

        Try
            oWriter = New StreamWriter(sPath, False, Encoding.GetEncoding(Charset))
            oWriter.Write(Message)
        Finally
            If Not (oWriter Is Nothing) Then
                oWriter.Close()
                oWriter = Nothing
            End If
        End Try
    End Sub

    ''' <summary>
    ''' 登录 
    ''' </summary>
    ''' <param name="sCluster">Cluster名称</param>
    ''' <param name="sAppName">应用名称</param>
    ''' <param name="sDomain">域，默认为空</param>
    ''' <param name="sUserID">用户名</param>
    ''' <param name="sToken">Token，默认为空</param>
    ''' <param name="sPassword">密码</param>
    ''' <remarks></remarks>
    Public Sub Login(ByVal sCluster As String, ByVal sAppName As String, ByVal sDomain As String,
                                      ByVal sUserID As String, ByVal sToken As String, ByVal sPassword As String)
        Try
            ' TODO Revise to Use Client / Server API, Not use Web Server
            Dim cManagerApps As HFMwManageApplications = New HFMwManageApplications
            cManagerApps.SetLogonInfoSSO(sDomain, sUserID, sToken, sPassword)
            cWebSession = cManagerApps.OpenApplication(sCluster, sAppName)
            cSession = cWebSession.session
        Catch ex As Exception
            cClient = Nothing
            cSession = Nothing
            Throw ex
        End Try
    End Sub

    ''' <summary>
    ''' 退出登录 
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Logout()
        cClient = Nothing
        cServer = Nothing
        cSession = Nothing
        cWebSession = Nothing
    End Sub

    ''' <summary>
    ''' 获取当前登录的用户 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetUsername() As String
        Dim sUsername As String = ""

        DirectCast(cSession.SystemInfo, HsvSystemInfo).GetUserName(sUsername)
        GetUsername = sUsername
    End Function

    ''' <summary>
    ''' 拆分字符串为Array (8201)   
    ''' </summary>
    ''' <param name="text">文本</param>
    ''' <param name="spliter">分隔符</param>
    ''' <returns></returns>
    ''' <remarks>
    '''     Split函数拆分的类型为8200, 这个数据类型不为HFM所接纳。
    '''     本函数将Split的结果再加工，返回类型为8201的结果
    ''' TODO  HFM COM为什么不接受 8200 的参数
    ''' </remarks>
    Public Function SplitText(ByVal text As String, ByVal spliter As String)
        Dim temp = Split(text, spliter)
        Dim Results(temp.Length)
        temp.CopyTo(Results, 0)
        SplitText = Results
    End Function


    ''' <summary>
    ''' 导出日记帐
    ''' </summary>
    ''' <param name="sYear">年</param>
    ''' <param name="sPeriod">月</param>
    ''' <param name="sScenario">场景</param>
    ''' <param name="sEntity">实体</param>
    ''' <param name="sValue">Value</param>
    ''' <param name="sPath">日记帐文件路径</param>
    ''' <returns></returns>
    ''' <remarks>
    '''     TODO 这里用的是Web Client，引用的程序集非Client/Server, 而是 Web Server 
    ''' </remarks>
    Public Function ExtractJournals(ByVal sYear, ByVal sPeriod, ByVal sScenario, ByVal sEntity, ByVal sValue, ByVal sPath) As String
        Dim cHsvWebClient As HsvWebClient

        Try
            cHsvWebClient = New HsvWebClient
            cHsvWebClient.SetSession(cSession)

            ' TODO 将下面三个变量 类型设置为Boolean，测试是否有影响
            ' TODO Extract Std Template Option
            Dim optExtractStdTmpls As Boolean = False
            ' TODO Extract Recycle Template Option
            Dim optExtractRecTmpls As Boolean = False
            ' TODO Extract Journals Option
            Dim optExtractJournals As Boolean = True

            'HFM Period
            Dim aPeriods = SplitText(sPeriod, ";")
            'HFM Entity
            Dim aEntities = SplitText(sEntity, ";")
            'HFM Value
            Dim aValues = SplitText(sValue, ";")
            'HFM Label
            Dim aLabels = SplitText("", ";")
            'HFM Journal Group
            Dim aGroups = SplitText("", ";")
            ' TODO HFM Journal Status
            Dim aStatus = New Integer() {0, 1, 2, 3, 4, 5}
            ' TODO HFM Journal Type
            Dim aType = New Integer() {0, 1, 2, 0, 4, 0, 0, 0, 8}
            ' TODO HFM Jounal Balance Type
            Dim aBalanceType = New Integer() {0, 1, 2, 0, 4}
            ' HFM Journal Delim Char
            Dim sDelimChar As String = ";"

            ' 使用WebClient 接口导出日记帐
            ' TODO Review whether can be replace by Client/Server API
            cHsvWebClient.ExtractJournalEx(optExtractStdTmpls, optExtractRecTmpls, _
                                            optExtractJournals, sScenario, sYear, aPeriods, aEntities, _
                                            aValues, aLabels, aGroups, aStatus, aType, aBalanceType, _
                                            sDelimChar, sPath)

            ExtractJournals = ""

        Catch
            ExtractJournals = "ERROR"

        Finally
            cHsvWebClient = Nothing

        End Try


    End Function

    ''' <summary>
    ''' 获取文件内容，使用GB2312 编码
    ''' TODO 为什么使用GB2312编码
    ''' </summary>
    ''' <param name="sPath"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetFileContent(ByVal sPath As String) As String
        GetFileContent = LoadFile(sPath, "GB2312")
    End Function

    ''' <summary>
    ''' 写入文件
    ''' TODO 为什么使用GB2312编码
    ''' 
    ''' </summary>
    ''' <param name="sPath"></param>
    ''' <param name="sContent"></param>
    ''' <remarks></remarks>
    Public Function SetFileContent(ByVal sPath As String, ByVal sContent As String) As String
        sContent = Replace(sContent, "\n", vbCr + vbLf)
        WriteToFile(sPath, sContent, "GB2312")

        SetFileContent = ""
    End Function

    ''' <summary>
    ''' 加载日记帐
    ''' </summary>
    ''' <param name="sPath">文件路径</param>
    ''' <param name="sLog">日志文件路径</param>
    ''' <returns>
    '''     成功 - 空字符串
    '''     失败 - 错误信息
    ''' </returns>
    ''' <remarks>
    '''     使用HsvJournalLoadACV
    ''' </remarks>
    Public Function LoadJournals(ByVal sPath As String, ByVal sLog As String) As String
        Dim cJournalsLoadACV As HsvJournalLoadACV
        Dim cLoadOptions, cLoadOption, sOption, curValue
        Dim sMessage As String = ""

        LoadJournals = ""
        Try
            ' 使用JournalsLoadACV
            ' TODO ACV 代表什么含义
            cJournalsLoadACV = New HsvJournalLoadACV
            cJournalsLoadACV.SetSession(cSession)

            cLoadOptions = cJournalsLoadACV.LoadOptions
            For Each cLoadOption In cLoadOptions
                sOption = cLoadOption.Name
                curValue = cLoadOption.CurrentValue

                Select Case VarType(curValue)
                    Case 11     ' bool
                        ' TODO Option=11 是什么含义
                        cLoadOption.CurrentValue = True

                    Case 8      ' bstr
                        ' TODO Option=11 是什么含义
                        cLoadOption.CurrentValue = ";"
                End Select
            Next

            ' TODO Item(1) 的写法和上面有什么不同？
            cLoadOptions.Item(1).CurrentValue = ";"

            cJournalsLoadACV.Load(sPath, sLog)

        Catch ex As Exception
            sMessage = LoadFile(sLog, "GB2312")

            ' 这里的判断标准是什么含义
            If InStr(sMessage, "!") > 0 Or UBound(Split(sMessage, vbLf)) >= 5 Then
                LoadJournals = sMessage
            Else
                LoadJournals = ex.ToString()
            End If
        Finally
            cJournalsLoadACV = Nothing
        End Try

    End Function


    ''' <summary>
    ''' 导出元数据
    ''' TODO sExtractOptions 给一个示例　
    ''' </summary>
    ''' <param name="sDataPath">数据文件路径</param>
    ''' <param name="sLogPath">日志文件路径</param>
    ''' <param name="sExtractOptions">导出选项</param>
    ''' <param name="sDelimiter">分隔符</param>
    ''' <param name="iFileFormat">文件格式</param>
    ''' <remarks></remarks>
    Public Function ExtractDimensions(ByVal sDataPath As String, ByVal sLogPath As String, ByVal sExtractOptions As String,
                               ByVal sDelimiter As String, ByVal iFileFormat As Integer) As String

        Dim cMetaLoadACV As HsvMetadataLoadACV
        Dim session As HsvSession
        Dim cExtractOption, cExtractOptions
        Dim aOptions
        Dim aData
        Dim sOption


        Try
            ' TODO 使用HsvMetadataLoadACV，如何界定
            cMetaLoadACV = New HsvMetadataLoadACV

            ' TODO Review 使用cSession的Session()，这个是什么情况？
            session = cSession.session()
            cMetaLoadACV.SetSession(session)

            cExtractOptions = cMetaLoadACV.ExtractOptions
            ' TODO Replace(sExtractOptions, " ", "") 这个是什么意思
            aOptions = SplitText(Replace(sExtractOptions, " ", ""), ";")

            ' Options for cExtractOption
            ' Currencies, Scenarios, Years, Periods, Views, Entities, Accounts, Custom1, Custom2, Custom3, Custom4
            ' AppSettings, ConsolMethods, ExtractSystemMembers, SystemAccounts, Values, ICPs
            For Each cExtractOption In cExtractOptions
                sOption = cExtractOption.Name

                Select Case sOption
                    ' TODO 总共有哪些选项

                    Case "Delimiter"
                        cExtractOption.CurrentValue = sDelimiter

                    Case "FileFormat"
                        cExtractOption.CurrentValue = iFileFormat

                    Case Else
                        ' TODO 这段什么意思　
                        aData = Filter(aOptions, sOption)
                        If UBound(aData) = 0 And LBound(aData) = 0 Then
                            If aData(0) = sOption Then
                                cExtractOption.CurrentValue = True
                            Else
                                cExtractOption.CurrentValue = False
                            End If
                        Else
                            cExtractOption.CurrentValue = False
                        End If
                End Select
            Next

            ' 导出元数据
            cMetaLoadACV.Extract(sDataPath, sLogPath)

        Finally
            cMetaLoadACV = Nothing
        End Try
    End Function


    ''' <summary>
    ''' 提取权限信息
    ''' </summary>
    ''' <param name="sDataPath">数据文件路径</param>
    ''' <param name="sLogPath">日志文件路径</param>
    ''' <param name="sExtractOptions">导出选项</param>
    ''' <param name="sDelimiter">分隔符</param>
    ''' <param name="iFileFormat">文件格式</param>
    ''' <remarks></remarks>
    Public Sub ExtractSecurity(ByVal sDataPath As String, ByVal sLogPath As String, ByVal sExtractOptions As String,
                               ByVal sDelimiter As String, ByVal iFileFormat As Integer)

        Dim cSecurityLoadACV As HsvSecurityLoadACV
        Dim session As HsvSession
        Dim cExtractOption, cExtractOptions
        Dim aOptions
        Dim aData
        Dim sOption

        Try
            ' 使用HsvSecurityLoadACV
            cSecurityLoadACV = New HsvSecurityLoadACV

            ' TODO 为什么使用csession.Session()
            session = cSession.session()
            cSecurityLoadACV.SetSession(session)

            cExtractOptions = cSecurityLoadACV.ExtractOptions
            aOptions = SplitText(Replace(sExtractOptions, " ", ""), ";")

            ' Options for cExtractOption
            ' Users, SecurityClasses, RoleAccess, SecurityClassAccess
            For Each cExtractOption In cExtractOptions
                sOption = cExtractOption.Name

                Select Case sOption
                    Case "Delimiter"
                        cExtractOption.CurrentValue = sDelimiter
                    Case "FileFormat"
                        cExtractOption.CurrentValue = iFileFormat
                    Case Else

                        ' TODO 这段什么意思
                        aData = Filter(aOptions, sOption)
                        If UBound(aData) = 0 And LBound(aData) = 0 Then
                            If aData(0) = sOption Then
                                cExtractOption.CurrentValue = True
                            Else
                                cExtractOption.CurrentValue = False
                            End If
                        Else
                            cExtractOption.CurrentValue = False
                        End If
                End Select
            Next

            cSecurityLoadACV.Extract(sDataPath, sLogPath)
        Finally

            cSecurityLoadACV = Nothing
        End Try

    End Sub


    '=================================================
    ' <summary>
    ' Description:  检查用户权限
    ' Calls:            
    ' Called By:     
    ' Parameter:   
    ' Others:         
    ' </summary>
    ' <returns></returns>
    '  当所输入的维度不存在的时候，会返回这样的异常
    '  System.Runtime.InteropServices.COMException (0x8004023B): Exception from HRESULT: 0x8004023B at HSVSECURITYACCESSLib.IHsvDataSecurity.GetCellLevelAccessRights(Int32 lScenario, Int32 lYear, Int32 lPeriod, Int32 lEntity, Int32 lParent, Int32 lValue, Int32 lAccount, Int32 lICP, Int32 lCustom1, Int32 lCustom2, Int32 lCustom3, Int32 lCustom4, Int32& plAccessRights)
    '=================================================
    ''' <summary>
    ''' 检查用户权限
    ''' </summary>
    ''' <param name="sScenario">Scenario</param>
    ''' <param name="sYear">Year</param>
    ''' <param name="sPeriod">Period</param>
    ''' <param name="sEntity">Entity</param>
    ''' <param name="sParent">Parent</param>
    ''' <param name="sValue">Value</param>
    ''' <param name="sAccount">Account</param>
    ''' <param name="sICP">ICP</param>
    ''' <param name="sCustom1">Custom1</param>
    ''' <param name="sCustom2">Custom2</param>
    ''' <param name="sCustom3">Custom3</param>
    ''' <param name="sCustom4">Custom4</param>
    ''' <param name="priority">读写权限</param>
    ''' <returns></returns>
    ''' <remarks>
    ''' TODO priority 的取值范围　
    ''' 
    '''     当所输入的维度不存在的时候，会返回这样的异常 System.Runtime.InteropServices.COMException (0x8004023B): Exception from HRESULT: 0x8004023B at HSVSECURITYACCESSLib.IHsvDataSecurity.GetCellLevelAccessRights 
    '''     Int32 lScenario, Int32 lYear, Int32 lPeriod, Int32 lEntity, Int32 lParent, Int32 lValue, Int32 lAccount, Int32 lICP, Int32 lCustom1, Int32 lCustom2, Int32 lCustom3, Int32 lCustom4, Int32 and plAccessRights
    ''' </remarks>
    Public Function CheckSecurity(ByVal sScenario As String, ByVal sYear As String, ByVal sPeriod As String,
                           ByVal sEntity As String, ByVal sParent As String, ByVal sValue As String, ByVal sAccount As String, ByVal sICP As String,
                           ByVal sCustom1 As String, ByVal sCustom2 As String, ByVal sCustom3 As String, ByVal sCustom4 As String,
                           ByVal priority As Integer) As Boolean
        Try
            Dim cMetadata As HsvMetadata = cSession.Metadata

            Dim cSecurityAccess As IHsvDataSecurity = cSession.Security

            Dim security As Integer
            cSecurityAccess.GetCellLevelAccessRights(DirectCast(cMetadata.Scenarios, IHsvTreeInfo).GetItemID(sScenario), _
                                                    DirectCast(cMetadata.Years, IHsvTreeInfo).GetItemID(sYear), _
                                                    DirectCast(cMetadata.Periods, IHsvTreeInfo).GetItemID(sPeriod), _
                                                    DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(sEntity), _
                                                    DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(sParent), _
                                                    DirectCast(cMetadata.Values, IHsvTreeInfo).GetItemID(sValue), _
                                                    DirectCast(cMetadata.Accounts, IHsvTreeInfo).GetItemID(sAccount), _
                                                    DirectCast(cMetadata.ICPs, IHsvTreeInfo).GetItemID(sICP), _
                                                    DirectCast(cMetadata.Custom1, IHsvTreeInfo).GetItemID(sCustom1), _
                                                    DirectCast(cMetadata.Custom2, IHsvTreeInfo).GetItemID(sCustom2), _
                                                    DirectCast(cMetadata.Custom3, IHsvTreeInfo).GetItemID(sCustom3), _
                                                    DirectCast(cMetadata.Custom4, IHsvTreeInfo).GetItemID(sCustom4), _
                                                    security)

            ' TODO Priority 的取值范围　
            CheckSecurity = (security >= priority)
        Catch ex As Exception
            CheckSecurity = False
        End Try
    End Function

    ''' <summary>
    ''' 获取语言ID 
    ''' </summary>
    ''' <param name="sLanguage">语言名称</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetLanguageID(ByVal sLanguage As String) As Integer
        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim pvaralIDs As Integer() = Nothing
        Dim pvarabstrLabels As String() = Nothing
        Dim index As Integer = -1
        Dim nLanaguageID As Integer = -1

        ' 使用Metadata类接口权举所有的语言
        cMetadata.EnumLanguages(pvaralIDs, pvarabstrLabels)
        For index = LBound(pvaralIDs) To UBound(pvaralIDs)
            If pvarabstrLabels(index) = sLanguage Then
                nLanaguageID = pvaralIDs(index)
                Exit For
            End If
        Next index

        ' TODO 这一段什么意思
        If nLanaguageID < 0 And pvarabstrLabels.Length > 0 Then
            nLanaguageID = pvaralIDs(LBound(pvaralIDs))
        End If

        GetLanguageID = nLanaguageID
    End Function

    ''' <summary>
    ''' 获取成员列表
    ''' </summary>
    ''' <param name="sLanguage">语言</param>
    ''' <param name="cTreeInfo">Metadata的维度对象</param>
    ''' <param name="hasParent">选项</param>
    ''' <returns></returns>
    ''' <remarks>
    ''' TODO cTreeinfo 举例
    ''' TODO hasParent 举例
    ''' </remarks>
    Private Function GetMemberList(ByVal sLanguage As String, ByVal cTreeInfo As IHsvTreeInfo, ByVal hasParent As Boolean) As String

        Dim index As Integer = -1
        Dim vaParIDs As Integer() = Nothing
        Dim sLabel As String = ""
        Dim sbText As StringBuilder = New StringBuilder

        Dim vaChildIDs As Integer() = Nothing
        Dim sParLabel As String = ""
        Dim sDesc As String = ""
        Dim lEnt As Long = -1

        ' 获取成员列表
        cTreeInfo.EnumMembers(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, lEnt, vaChildIDs, vaParIDs)
        For index = LBound(vaChildIDs) To UBound(vaChildIDs)
            If hasParent Then
                cTreeInfo.GetLabel(CLng(vaParIDs(index)), sParLabel)
            End If

            cTreeInfo.GetLabel(CLng(vaChildIDs(index)), sLabel)
            cTreeInfo.GetDescription(vaChildIDs(index), GetLanguageID(sLanguage), sDesc)

            If hasParent And sParLabel.Trim() <> "" Then
                ' TODO  有父级的情况，如Entity
                sbText.Append(String.Format("{1}{0}{2}.{1}{0}{3}{4}", vbTab, sLabel, sParLabel, sDesc, vbCr + vbLf))
            Else
                ' TODO  不需要父级的情况，如Account
                sbText.Append(String.Format("{1}{0}{1}{0}{3}{4}", vbTab, sLabel, "", sDesc, vbCr + vbLf))
            End If
        Next index

        GetMemberList = sbText.ToString()

    End Function

    ''' <summary>
    ''' 获取成员列表
    ''' </summary>
    ''' <param name="sLanguage">语言</param>
    ''' <param name="cTreeInfo">元数据对象</param>
    ''' <param name="hasParent">是否需要父级</param>
    ''' <param name="memberlistname">成员列表</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDynamicMemberList(ByVal sLanguage As String, ByVal cTreeInfo As IHsvTreeInfo, ByVal hasParent As Boolean, ByVal memberlistname As String) As String

        Dim index As Integer = -1
        Dim vaParIDs As Integer() = Nothing
        Dim lListID As Integer = -1
        Dim sDesc As String = ""
        Dim sbText As StringBuilder = New StringBuilder

        Dim vaChildIDs As Integer() = Nothing
        Dim sParLabel As String = ""
        Dim sLabel As String = ""
        Dim lEnt As Long = -1


        If Not String.IsNullOrEmpty(memberlistname) Then
            ' 如果有列表，则取列表对应的成员
            cTreeInfo.GetMemberListID(memberlistname, lListID)
            cTreeInfo.EnumMembers(lListID, lEnt, vaChildIDs, vaParIDs)
        Else
            ' 如果没有列表，则取架构的所有成员
            cTreeInfo.EnumMembers(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, lEnt, vaChildIDs, vaParIDs)
        End If

        ' 遍历 vaChildIDs, vaParIDs 的所有成员
        For index = LBound(vaChildIDs) To UBound(vaChildIDs)
            ' 获取父级成员的编码
            If hasParent And Not (vaParIDs Is Nothing) Then
                cTreeInfo.GetLabel(CLng(vaParIDs(index)), sParLabel)

                If sParLabel Is Nothing Then sParLabel = ""
            End If

            ' 获取子级成员的编码和描述
            cTreeInfo.GetLabel(CLng(vaChildIDs(index)), sLabel)
            cTreeInfo.GetDescription(vaChildIDs(index), GetLanguageID(sLanguage), sDesc)

            If hasParent And sParLabel.Trim() <> "" Then
                ' TODO 使用 String.Format
                sbText.Append(sParLabel + vbTab + sLabel + vbTab + sParLabel + "." + sLabel + vbTab + sDesc + vbTab + sParLabel + "." + sLabel + " - " + sDesc + vbCr + vbLf)
            Else
                ' TODO 使用 String.Format
                sbText.Append("" + vbTab + sLabel + vbTab + sLabel + vbTab + sDesc + vbTab + sLabel + " - " + sDesc + vbCr + vbLf)
            End If
        Next index

        GetDynamicMemberList = sbText.ToString()
    End Function


    ''' <summary>
    ''' 获取所有的成员列表
    ''' 
    ''' TODO GetMemberList 和 GetMemberListEx的区别
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="cTreeInfo"></param>
    ''' <param name="hasParent"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function GetMemberListEx(ByVal sLanguage As String, ByVal cTreeInfo As IHsvTreeInfo, ByVal hasParent As Boolean) As List(Of MetaItem)

        Dim index As Integer = -1
        Dim vaParIDs As Integer() = Nothing
        Dim sDesc As String = ""
        Dim sbText As StringBuilder = New StringBuilder
        Dim aMetaList As List(Of MetaItem) = New List(Of MetaItem)
        Dim oMetaitem As MetaItem

        Dim vaChildIDs As Integer() = Nothing
        Dim sParLabel As String = ""
        Dim sLabel As String = ""
        Dim lEnt As Long = -1

        ' TODO 列出架构中所有的成员，是否可以和 ExtractMemberList, ExtractDynamicsMemberList 合并
        cTreeInfo.EnumMembers(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, lEnt, vaChildIDs, vaParIDs)

        For index = LBound(vaChildIDs) To UBound(vaChildIDs)
            ' 获取父级标签　
            If hasParent Then
                cTreeInfo.GetLabel(CLng(vaParIDs(index)), sParLabel)
            End If

            cTreeInfo.GetLabel(CLng(vaChildIDs(index)), sLabel)
            cTreeInfo.GetDescription(vaChildIDs(index), GetLanguageID(sLanguage), sDesc)

            oMetaitem = New MetaItem
            oMetaitem.ShortName = sLabel
            oMetaitem.Description = sDesc

            If hasParent And sParLabel.Trim() <> "" Then
                oMetaitem.FullName = sParLabel + "." + sLabel
            Else
                oMetaitem.FullName = sLabel
            End If

            aMetaList.Add(oMetaitem)
        Next index

        GetMemberListEx = aMetaList
    End Function

    ''' <summary>
    ''' 获取所有的Entity
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="sMemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetEntities(ByVal sLanguage As String, ByVal sMemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetEntities = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetAccountLastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Entities, True, sMemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Account
    ''' 
    ''' todo new code, to be Review
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetAccounts(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetAccounts = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetAccountLastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Accounts, False, MemberListName)
    End Function

    ''' <summary>
    ''' 获取所有的ICP
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetICPs(ByVal sLanguage As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetICPs = GetMemberList(sLanguage, cMetadata.ICPs, False)
    End Function


    ''' <summary>
    ''' 获取所有的Year
    ''' 
    '''  todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetYears(ByVal sLanguage As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetYears = GetMemberList(sLanguage, cMetadata.Years, False)
    End Function


    ''' <summary>
    ''' 获取所有的Period
    ''' 
    '''  todo new code, to be Review
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPeriods(ByVal sLanguage As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetPeriods = GetMemberList(sLanguage, cMetadata.Periods, False)
    End Function


    ''' <summary>
    ''' 获取所有的Custom1
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom1(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetCustom1 = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom1LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Custom1, False, MemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Custom2
    ''' 
    '''  todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom2(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetCustom2 = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom2LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Custom2, False, MemberListName)
    End Function

    ''' <summary>
    ''' 获取所有的Custom3
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom3(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetCustom3 = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom3LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Custom3, False, MemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Custom4
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom4(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetCustom4 = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Custom4, False, MemberListName)
    End Function



    ''' <summary>
    ''' 获取所有的维度
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDimension(ByVal sLanguage As String, ByVal DimName As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim cDimension As Object
        Select Case DimName.ToUpper()
            Case "ACCOUNT"
                cDimension = cMetadata.Accounts
            Case "ENTITY"
                cDimension = cMetadata.Entities
            Case "SCENARIO"
                cDimension = cMetadata.Scenarios
            Case "YEAR"
                cDimension = cMetadata.Years
            Case "PERIOD"
                cDimension = cMetadata.Periods
            Case "VALUE"
                cDimension = cMetadata.Values
            Case "VIEW"
                cDimension = cMetadata.Views
            Case "ICP"
                cDimension = cMetadata.ICPs
            Case "CUSTOM1"
                cDimension = cMetadata.Custom1
            Case "CUSTOM2"
                cDimension = cMetadata.Custom2
            Case "CUSTOM3"
                cDimension = cMetadata.Custom3
            Case "CUSTOM4"
                cDimension = cMetadata.Custom4
            Case Else
                cDimension = Nothing
        End Select

        Return GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cDimension, True, MemberListName)
    End Function


    Public Function GetApplicationWithAll() As DataTable
        Dim Target As DataTable = New DataTable()

        'Target.Merge(GetMetadataWithAll("ACCOUNT"))
        'Target.Merge(GetMetadataWithAll("ENTITY"))
        'Target.Merge(GetMetadataWithAll("SCENARIO"))
        'Target.Merge(GetMetadataWithAll("ACCOUNT"))
        'Target.Merge(GetMetadataWithAll("YEAR"))
        'Target.Merge(GetMetadataWithAll("PERIOD"))
        'Target.Merge(GetMetadataWithAll("VALUE"))
        'Target.Merge(GetMetadataWithAll("VIEW"))
        'Target.Merge(GetMetadataWithAll("ICP"))
        'Target.Merge(GetMetadataWithAll("CUSTOM1"))
        'Target.Merge(GetMetadataWithAll("CUSTOM2"))
        'Target.Merge(GetMetadataWithAll("CUSTOM3"))
        'Target.Merge(GetMetadataWithAll("CUSTOM4"))
        'Target.Merge(GetMetadataWithAll("SINGLEENTITY"))
        'Target.Merge(GetMetadataWithAll("BALANCING"))
        'Target.Merge(GetMetadataWithAll("TYPE"))
        'Target.Merge(GetMetadataWithAll("JOURNALGROUP"))
        'Target.Merge(GetMetadataWithAll("LABEL"))
        'Target.Merge(GetMetadataWithAll("TYPE"))
        'Target.Merge(GetMetadataWithAll("SECURITYCLASS"))
        'Target.Merge(GetMetadataWithAll("DEBIT"))
        'Target.Merge(GetMetadataWithAll("CREDIT"))


        Return Target
    End Function

    ''' <summary>
    ''' 获取所有的维度
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMetadataWithAll(ByVal DimName As String, ByVal bDefaultWithParent As Boolean) As DataTable
        Dim cMetadata As HsvMetadata = cSession.Metadata


        Select Case DimName.ToUpper()
            Case "ACCOUNT"
                Return GetDimensionWithAll(DimName, cMetadata.Accounts, bDefaultWithParent)
            Case "ENTITY"
                Return GetDimensionWithAll(DimName, cMetadata.Entities, bDefaultWithParent)
            Case "SCENARIO"
                Return GetDimensionWithAll(DimName, cMetadata.Scenarios, bDefaultWithParent)
            Case "YEAR"
                Return GetDimensionWithAll(DimName, cMetadata.Years, bDefaultWithParent)
            Case "PERIOD"
                Return GetDimensionWithAll(DimName, cMetadata.Periods, bDefaultWithParent)
            Case "VALUE"
                Return GetDimensionWithAll(DimName, cMetadata.Values, bDefaultWithParent)
            Case "VIEW"
                Return GetDimensionWithAll(DimName, cMetadata.Views, bDefaultWithParent)
            Case "ICP"
                Return GetDimensionWithAll(DimName, cMetadata.ICPs, bDefaultWithParent)
            Case "CUSTOM1"
                Return GetDimensionWithAll(DimName, cMetadata.Custom1, bDefaultWithParent)
            Case "CUSTOM2"
                Return GetDimensionWithAll(DimName, cMetadata.Custom2, bDefaultWithParent)
            Case "CUSTOM3"
                Return GetDimensionWithAll(DimName, cMetadata.Custom3, bDefaultWithParent)
            Case "CUSTOM4"
                Return GetDimensionWithAll(DimName, cMetadata.Custom4, bDefaultWithParent)
            Case "SINGLEENTITY"
                Return GetDimensionWithAll(DimName, cMetadata.Entities, bDefaultWithParent)

            Case "BALANCING"
                'Return GetEmptyWithAll(DimName)
                Dim objDict As Dictionary(Of String, String) = New Dictionary(Of String, String)
                objDict.Add("B", "平衡")
                objDict.Add("U", "不平衡")
                'objDict.Add("E", "Balance By Entity")
                Return GetDefaultWithAll(DimName, objDict)

            Case "TYPE"
                'Return GetEmptyWithAll(DimName)
                Dim objDict As Dictionary(Of String, String) = New Dictionary(Of String, String)
                objDict.Add("W", "Working")
                objDict.Add("P", "Posted")
                Return GetDefaultWithAll(DimName, objDict)

            Case "JOURNALGROUP"
                Return GetJournalGroupWithAll(DimName)

            Case "LABEL"
                Return GetEmptyWithAll(DimName)

            Case "SECURITYCLASS"
                Return GetSecurityClassWithAll(DimName)

            Case "DESCRIPTION"
                Return GetEmptyWithAll(DimName)

            Case "DEBIT"
                Return GetEmptyWithAll(DimName)

            Case "CRIDIT"
                Return GetEmptyWithAll(DimName)

            Case Else
                Return GetEmptyWithAll(DimName)
        End Select

        'Dimension  Key     ParentKey       FullPath        Default     Alias1      Alias2      Alias3      Alias4

    End Function


    ''' <summary>
    ''' 获取成员列表
    ''' </summary>
    ''' <param name="cTreeInfo">元数据对象</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDimensionWithAll(ByVal sDimName As String, cTreeInfo As IHsvTreeInfo, bDefaultWithParent As Boolean) As DataTable

        Dim index As Integer = -1
        Dim vaChildDescs As String() = Nothing
        Dim vaChildLabels As String() = Nothing
        Dim vaParentIDs As Integer() = Nothing
        Dim vaChildIDs As Integer() = Nothing
        Dim vabHasChilden As Short() = Nothing
        Dim dtTarget As DataTable = New DataTable()
        Dim dictItmes As Dictionary(Of Integer, DataRow) = New Dictionary(Of Integer, DataRow)
        Dim row As DataRow
        Dim parentrow As DataRow = Nothing
        Dim lastrow As DataRow = Nothing

        dtTarget.Columns.Add("Dimension")
        dtTarget.Columns.Add("ID")
        dtTarget.Columns.Add("ParentID")
        dtTarget.Columns.Add("Key")
        dtTarget.Columns.Add("ParentKey")
        dtTarget.Columns.Add("Path")
        dtTarget.Columns.Add("Default")
        dtTarget.Columns.Add("Alias1")
        dtTarget.Columns.Add("Alias2")
        dtTarget.Columns.Add("Alias3")
        dtTarget.Columns.Add("Alias4")
        dtTarget.Columns.Add("Attr1")
        dtTarget.Columns.Add("Attr2")
        dtTarget.Columns.Add("Attr3")
        dtTarget.Columns.Add("Attr4")


        'dtTarget.PrimaryKey = New DataColumn() {dtTarget.Columns("Dimension"), dtTarget.Columns("ID"), dtTarget.Columns("ParentID")}

        cTreeInfo.EnumAllParentAndChildIDs(vaParentIDs, vaChildIDs)
        cTreeInfo.GetDisplayInfoForSeveralItems(HFMConstantsLib.tagSYSTEMLISTS.MEMBER_LIST_DESCENDANTS, _
                                                vaChildIDs, vaParentIDs, vabHasChilden, vaChildLabels, vaChildDescs)

        If vaChildIDs Is Nothing Then
            Return dtTarget
        End If

        Dim arrLabel


        ' 遍历 vaChildIDs, vaParIDs 的所有成员
        For index = LBound(vaChildLabels) To UBound(vaChildLabels)
            'parentrow = IIf(dictItmes.ContainsKey(vaParentIDs(index)), dictItmes.Item(vaParentIDs(index)), Nothing)
            If Not (dictItmes.TryGetValue(vaParentIDs(index), parentrow)) Then
                parentrow = Nothing
            End If

            'parentrow = IIf(dictItmes.ContainsKey(vaParentIDs(index)), dictItmes.Item(vaParentIDs(index)), Nothing)
            If Not (dictItmes.TryGetValue(vaChildIDs(index), lastrow)) Then
                lastrow = Nothing
            End If

            arrLabel = Split(IIf(InStr(vaChildLabels(index), ".") > 0, vaChildLabels(index), "." + vaChildLabels(index)), ".")

            If Not (parentrow Is Nothing) Then
                ' 获取父级成员的编码
                If bDefaultWithParent Then
                    row = dtTarget.Rows.Add(sDimName, vaChildIDs(index), vaParentIDs(index), vaChildLabels(index), parentrow("Key"), _
                                        parentrow("Path") + "\" + vaChildLabels(index), vaChildLabels(index) + "-" + vaChildDescs(index), _
                                        arrLabel(1), vaChildDescs(index), vaChildLabels(index), "",
                                        If(vaParentIDs.Contains(vaChildIDs(index)), "Y", "N"), "", "", "")
                Else
                    row = dtTarget.Rows.Add(sDimName, vaChildIDs(index), vaParentIDs(index), arrLabel(1), arrLabel(0), _
                                        parentrow("Path") + "\" + arrLabel(1), arrLabel(1) + "-" + vaChildDescs(index), _
                                        arrLabel(1), vaChildDescs(index), vaChildLabels(index), "",
                                        If(vaParentIDs.Contains(vaChildIDs(index)), "Y", "N"), "", "", "")

                End If

                Dim newrow As DataRow
                If Not (lastrow Is Nothing) Then
                    Dim rows As DataRow()
                    rows = dtTarget.Select(String.Format("Path like '{0}\%'", EscapeLikeValue(lastrow("Path"))))
                    For Each each_row As DataRow In rows
                        newrow = dtTarget.Rows.Add()
                        newrow.ItemArray = each_row.ItemArray.Clone()
                        If bDefaultWithParent Then
                            newrow("Path") = newrow("Path").ToString().Replace(lastrow("Path"), parentrow("Path") + "\" + vaChildLabels(index))
                        Else
                            newrow("Path") = newrow("Path").ToString().Replace(lastrow("Path"), parentrow("Path") + "\" + arrLabel(1))
                        End If
                    Next each_row
                End If
            Else
                ' 获取父级成员的编码
                row = dtTarget.Rows.Add(sDimName, vaChildIDs(index), sDimName, arrLabel(1), sDimName, _
                                    "\" + sDimName + "\" + arrLabel(1), vaChildLabels(index) + "-" + vaChildDescs(index), _
                                    arrLabel(1), vaChildDescs(index), "", "",
                                    If(vaParentIDs.Contains(vaChildIDs(index)), "Y", "N"), "", "", "")


            End If

            If dictItmes.ContainsKey(vaChildIDs(index)) Then
                dictItmes(vaChildIDs(index)) = row
            Else
                dictItmes.Add(vaChildIDs(index), row)
            End If
            ' = row
        Next index

        Return dtTarget
    End Function


    Private Function EscapeLikeValue(valueWithoutWildcards As String) As String
        Dim sb As StringBuilder = New StringBuilder()
        For i As Int32 = 0 To valueWithoutWildcards.Length - 1
            Dim c As Char = valueWithoutWildcards(i)
            If c = "*" Or c = "%" Or c = "[" Or c = "]" Then

                sb.Append("[").Append(c).Append("]")
            ElseIf c = "\'" Then
                sb.Append("''")
            Else
                sb.Append(c)
            End If
        Next
        Return sb.ToString()
    End Function


    ''' <summary>
    ''' 获取所有的日记帐组
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetJournalGroupWithAll(sDimName As String) As DataTable

        Dim dtTarget As DataTable = New DataTable()

        dtTarget.Columns.Add("Dimension")
        dtTarget.Columns.Add("ID")
        dtTarget.Columns.Add("ParentID")
        dtTarget.Columns.Add("Key")
        dtTarget.Columns.Add("ParentKey")
        dtTarget.Columns.Add("Path")
        dtTarget.Columns.Add("Default")
        dtTarget.Columns.Add("Alias1")
        dtTarget.Columns.Add("Alias2")
        dtTarget.Columns.Add("Alias3")
        dtTarget.Columns.Add("Alias4")
        'dtTarget.PrimaryKey = New DataColumn() {dtTarget.Columns("Dimension"), dtTarget.Columns("ID"), dtTarget.Columns("ParentID")}

        Dim IHsJourEx As HsvJournals = cSession.Journals
        Dim index As Integer = -1
        Dim Desc As String() = Nothing
        Dim Str As StringBuilder = New StringBuilder
        Dim Vals As String() = Nothing

        DirectCast(IHsJourEx, IHsvJournalsEx).EnumJournalGroups(Vals, Desc)

        dtTarget.Rows.Add(sDimName, "[" + sDimName + "]", sDimName, "[" + sDimName + "]", sDimName, _
                           "\" + sDimName + "\" + "[" & sDimName & "]", "[" & sDimName & "]", _
                           "[" & sDimName & "]", "", "", "")

        If Not (Vals Is Nothing) Then
            For index = LBound(Vals) To UBound(Vals)
                ' TODO 只用到了 Vals, 但是没有用到 Desc，是否需要对接口进一步封装
                If Not (String.IsNullOrEmpty(Vals(index).Trim().ToString())) Then
                    ' 获取父级成员的编码
                    dtTarget.Rows.Add(sDimName, Vals(index), "[" & sDimName & "]", Vals(index), "[" & sDimName & "]", _
                                        "\" + sDimName + "\[" & sDimName & "]\" + Vals(index), Vals(index) + "-" + IIf(String.IsNullOrEmpty(Desc(index)), "", Desc(index)), _
                                        "", "", "", "")

                End If
            Next (index)
        End If

        ' TODO 返回的结果中都带用户、应用名称、更新时间，这里用的是GetCustom3LastUpdate，是否需要修改
        Return dtTarget
    End Function


    Public Function GetSecurityClassWithAll(sDimName As String) As DataTable
        Dim SecurityAccess As IHsvSecurityAccess = cSession.Security
        Dim vblSecurityClassIDs() As Integer = Nothing
        Dim vbstrSecurityClassNames() As String = Nothing
        Dim vblSecurityClassRights() As Integer = Nothing

        SecurityAccess.GetAllSecurityClassRightsForConnectedUser(vblSecurityClassIDs, vbstrSecurityClassNames, vblSecurityClassRights)

        Dim dtTarget As DataTable = New DataTable()

        dtTarget.Columns.Add("Dimension")
        dtTarget.Columns.Add("ID")
        dtTarget.Columns.Add("ParentID")
        dtTarget.Columns.Add("Key")
        dtTarget.Columns.Add("ParentKey")
        dtTarget.Columns.Add("Path")
        dtTarget.Columns.Add("Default")
        dtTarget.Columns.Add("Alias1")
        dtTarget.Columns.Add("Alias2")
        dtTarget.Columns.Add("Alias3")
        dtTarget.Columns.Add("Alias4")
        'dtTarget.PrimaryKey = New DataColumn() {dtTarget.Columns("Dimension"), dtTarget.Columns("ID"), dtTarget.Columns("ParentID")}

        dtTarget.Rows.Add(sDimName, "[" + sDimName + "]", sDimName, "[" + sDimName + "]", sDimName, _
                            "\" + sDimName + "\" + "[" & sDimName & "]", "[" & sDimName & "]", _
                            "[" & sDimName & "]", "", "", "")

        If vblSecurityClassIDs Is Nothing Then
            Return dtTarget

        End If

        Dim index As Integer
        For index = LBound(vblSecurityClassIDs) To UBound(vblSecurityClassIDs)

            If (vblSecurityClassRights(index) > HFMConstantsLib.HFM_NUM_ACCESS_TYPES.HFM_ACCESS_RIGHTS_READONLY) Then
                ' 获取父级成员的编码
                dtTarget.Rows.Add(sDimName, vblSecurityClassIDs(index), "[" & sDimName & "]", vbstrSecurityClassNames(index), "[" & sDimName & "]", _
                                    "\" + sDimName + "\[" & sDimName & "]\" + vbstrSecurityClassNames(index), vbstrSecurityClassNames(index), _
                                    "", "", "", "")

            End If
        Next (index)

        Return dtTarget

    End Function

    Public Function GetEmptyWithAll(sDimName As String) As DataTable
        Dim dtTarget As DataTable = New DataTable()

        dtTarget.Columns.Add("Dimension")
        dtTarget.Columns.Add("ID")
        dtTarget.Columns.Add("ParentID")
        dtTarget.Columns.Add("Key")
        dtTarget.Columns.Add("ParentKey")
        dtTarget.Columns.Add("Path")
        dtTarget.Columns.Add("Default")
        dtTarget.Columns.Add("Alias1")
        dtTarget.Columns.Add("Alias2")
        dtTarget.Columns.Add("Alias3")
        dtTarget.Columns.Add("Alias4")
        'dtTarget.PrimaryKey = New DataColumn() {dtTarget.Columns("Dimension"), dtTarget.Columns("ID"), dtTarget.Columns("ParentID")}

        dtTarget.Rows.Add(sDimName, "[NONE]", sDimName, "[NONE]", sDimName, _
                                    "\" + sDimName + "\[NONE]", "[NONE]", _
                                    "", "", "", "")

        Return dtTarget

    End Function

    Public Function GetDefaultWithAll(sDimName As String, sDimDefaultValue As Dictionary(Of String, String)) As DataTable
        Dim dtTarget As DataTable = New DataTable()

        dtTarget.Columns.Add("Dimension")
        dtTarget.Columns.Add("ID")
        dtTarget.Columns.Add("ParentID")
        dtTarget.Columns.Add("Key")
        dtTarget.Columns.Add("ParentKey")
        dtTarget.Columns.Add("Path")
        dtTarget.Columns.Add("Default")
        dtTarget.Columns.Add("Alias1")
        dtTarget.Columns.Add("Alias2")
        dtTarget.Columns.Add("Alias3")
        dtTarget.Columns.Add("Alias4")
        dtTarget.Columns.Add("Attr1")
        dtTarget.Columns.Add("Attr2")
        dtTarget.Columns.Add("Attr3")
        dtTarget.Columns.Add("Attr4")
        'dtTarget.PrimaryKey = New DataColumn() {dtTarget.Columns("Dimension"), dtTarget.Columns("ID"), dtTarget.Columns("ParentID")}

        dtTarget.Rows.Add(sDimName, "[" + sDimName + "]", sDimName, "[" + sDimName + "]", sDimName, _
                            "\" + sDimName + "\" + "[" & sDimName & "]", "[" & sDimName & "]", _
                            "[" & sDimName & "]", "", "", "")

        For Each key As String In sDimDefaultValue.Keys
            dtTarget.Rows.Add(sDimName, key, "[" + sDimName + "]", key, "[" + sDimName + "]", _
                                        "\" + sDimName + "\[" + sDimName + "]\" + key, key + "-" + sDimDefaultValue(key), _
                                        key, sDimDefaultValue(key), "", "")

        Next key

        Return dtTarget
    End Function

    Public Function GetConstraint(sDimName As String) As DataTable
        Dim cMetadata As HsvMetadata = cSession.Metadata

        Select Case sDimName.ToUpper()
            Case "ACCOUNT"
                Return GetConstraintForAccount(sDimName, cMetadata.Accounts)

            Case "ENTITY"
                Return GetConstraintForEntity(sDimName, cMetadata.Entities)

            Case Else
                Return GetConstraintForEmpty(sDimName)
        End Select

    End Function


    Public Function GetConstraintForAccount(sDimName As String, cTreeInfo As IHsvTreeInfo) As DataTable
        Dim index As Integer = -1
        Dim vaChildDescs As String() = Nothing
        Dim vaChildLabels As String() = Nothing
        Dim vaParentIDs As Integer() = Nothing
        Dim vaChildIDs As Integer() = Nothing
        Dim vabHasChilden As Short() = Nothing
        Dim dtTarget As DataTable = New DataTable()
        Dim drCurrenet As DataRow
        Dim lTopMember As Integer, sTopLabel As String

        dtTarget.Columns.Add("SourceDimension")
        dtTarget.Columns.Add("SourceMember")
        dtTarget.Columns.Add("TargetDimension")
        dtTarget.Columns.Add("TargetTopMember")
        dtTarget.Columns.Add("TargetDefault")

        Dim objAccounts As HsvAccounts
        objAccounts = DirectCast(cTreeInfo, HsvAccounts)

        Dim lEnt As Integer : lEnt = -1
        cTreeInfo.EnumMembers(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, lEnt, vaChildIDs, vaParentIDs)

        If vaChildIDs Is Nothing Then
            Return dtTarget
        End If

        lTopMember = -1
        sTopLabel = ""

        Dim sAccountLabel As String = ""
        Dim bIsICP As Boolean = False

        ' 遍历 vaChildIDs, vaParIDs 的所有成员
        For index = LBound(vaChildIDs) To UBound(vaChildIDs)
            cTreeInfo.GetLabel(vaChildIDs(index), sAccountLabel)

            objAccounts.GetTopMemberOfValidCustom1Hierarchy(vaChildIDs(index), lTopMember)
            DirectCast(DirectCast(cSession.Metadata, IHsvMetadata).Custom1, IHsvTreeInfo).GetLabel(lTopMember, sTopLabel)
            If UCase(sTopLabel) = "[NONE]" Then
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom1", sTopLabel, sTopLabel)
            Else
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom1", sTopLabel, "")
            End If

            objAccounts.GetTopMemberOfValidCustom2Hierarchy(vaChildIDs(index), lTopMember)
            DirectCast(DirectCast(cSession.Metadata, IHsvMetadata).Custom2, IHsvTreeInfo).GetLabel(lTopMember, sTopLabel)
            If UCase(sTopLabel) = "[NONE]" Then
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom2", sTopLabel, sTopLabel)
            Else
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom2", sTopLabel, "")
            End If

            objAccounts.GetTopMemberOfValidCustom3Hierarchy(vaChildIDs(index), lTopMember)
            DirectCast(DirectCast(cSession.Metadata, IHsvMetadata).Custom3, IHsvTreeInfo).GetLabel(lTopMember, sTopLabel)
            If UCase(sTopLabel) = "[NONE]" Then
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom3", sTopLabel, sTopLabel)
            Else
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom3", sTopLabel, "")
            End If
            

            objAccounts.GetTopMemberOfValidCustom4Hierarchy(vaChildIDs(index), lTopMember)
            DirectCast(DirectCast(cSession.Metadata, IHsvMetadata).Custom4, IHsvTreeInfo).GetLabel(lTopMember, sTopLabel)
            If UCase(sTopLabel) = "[NONE]" Then
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom4", sTopLabel, sTopLabel)
            Else
                dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "Custom4", sTopLabel, "")
            End If

            objAccounts.IsICP(vaChildIDs(index), bIsICP)
            dtTarget.Rows.Add("ACCOUNT", sAccountLabel, "ICP", IIf(bIsICP, "[ICP TOP]", "[ICP NONE]"), IIf(bIsICP, "", "[ICP NONE]"))

        Next index

        Return dtTarget
    End Function


    Public Function GetConstraintForEntity(sDimName As String, cTreeInfo As IHsvTreeInfo) As DataTable
        Dim index As Integer = -1
        Dim vaChildDescs As String() = Nothing
        Dim vaChildLabels As String() = Nothing
        Dim vaParentIDs As Integer() = Nothing
        Dim vaChildIDs As Integer() = Nothing
        Dim vabHasChilden As Short() = Nothing
        Dim dtTarget As DataTable = New DataTable()
        Dim lTopMember As Integer, sTopLabel As String

        dtTarget.Columns.Add("SourceDimension")
        dtTarget.Columns.Add("SourceMember")
        dtTarget.Columns.Add("TargetDimension")
        dtTarget.Columns.Add("TargetTopMember")
        dtTarget.Columns.Add("TargetDefault")

        Dim lEnt As Integer : lEnt = -1
        cTreeInfo.EnumMembers(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, lEnt, vaChildIDs, vaParentIDs)

        If vaChildIDs Is Nothing Then
            Return dtTarget
        End If

        lTopMember = -1
        sTopLabel = ""

        Dim sChildLabel As String = "", sParentLabel As String = ""
        Dim bIsICP As Boolean = False
        Dim sSecurityClasID As Integer = Nothing, sSecurityName As String = Nothing
        Dim objEntity As IHsvEntities
        Dim bHasChild As Short

        objEntity = DirectCast(cTreeInfo, IHsvEntities)
        ' 遍历 vaChildIDs, vaParIDs 的所有成员
        For index = LBound(vaChildIDs) To UBound(vaChildIDs)

            Try
                cTreeInfo.GetDisplayInfo(tagSYSTEMLISTS.MEMBER_LIST_ALL_HIERARCHY, vaChildIDs(index), vaParentIDs(index), _
                                            bHasChild, sChildLabel, sParentLabel)
                objEntity.GetSecurityClassID(vaChildIDs(index), sSecurityClasID)
                If sSecurityClasID > 0 Then
                    DirectCast(cSession.Security, IHsvSecurityAccess).GetSecurityClassLabel(sSecurityClasID, sSecurityName)
                    dtTarget.Rows.Add("ENTITY", sChildLabel, "SECURITYCLASS", sSecurityName, sSecurityName)
                End If
            Catch ex As Exception
                Throw New Exception(String.Format("Exception while index={0}, ID={1}, SID={2}", index, vaChildIDs(index), sSecurityClasID), ex)
            End Try

        Next index

        Return dtTarget
    End Function


    Public Function GetConstraintForEmpty(sDimName)
        Dim index As Integer = -1
        Dim vaChildDescs As String() = Nothing
        Dim vaChildLabels As String() = Nothing
        Dim vaParentIDs As Integer() = Nothing
        Dim vaChildIDs As Integer() = Nothing
        Dim vabHasChilden As Short() = Nothing
        Dim dtTarget As DataTable = New DataTable()

        dtTarget.Columns.Add("SourceDimension")
        dtTarget.Columns.Add("SourceMember")
        dtTarget.Columns.Add("TargetDimension")
        dtTarget.Columns.Add("TargetTopMember")
        dtTarget.Columns.Add("TargetDefault")

        Return dtTarget
    End Function



    ''' <summary>
    ''' 获取所有的Year
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetYear(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetYear = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Years, False, MemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Period
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPeirod(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetPeirod = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Periods, False, MemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Scenario
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetScenario(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetScenario = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Scenarios, False, MemberListName)
    End Function



    ''' <summary>
    ''' 获取所有的Scenario
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetView(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetView = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Views, False, MemberListName)
    End Function


    ''' <summary>
    ''' 获取所有的Value
    ''' 
    ''' todo new code, to be Review
    ''' 
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="MemberListName"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetValue(ByVal sLanguage As String, ByVal MemberListName As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetValue = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom4LastUpdate() + vbCr + vbLf + GetDynamicMemberList(sLanguage, cMetadata.Values, False, MemberListName)
    End Function

    ''' <summary>
    ''' 获取最新更新的时间
    ''' </summary>
    ''' <param name="DIMENSIONS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetLastUpdate(ByVal DIMENSIONS As Integer) As String
        Dim dTime As Double
        Dim cMetadata As HsvMetadata = cSession.Metadata

        ' TODO Confirm whether use Application Setting Stamp
        cMetadata.GetApplicationSettingsTimeStamp(dTime)
        Dim sDates As String = CDate(Date.FromOADate(dTime)).ToString()

        ' TODO Review whether use cTreeInfo.GetTreeTimeStamp(dTime)
        GetLastUpdate = sDates
    End Function


    ''' <summary>
    ''' 获取Account最后更新的时间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetAccountLastUpdate() As String
        GetAccountLastUpdate = GetLastUpdate(tagHFMDIMENSIONS.DIMENSIONACCOUNT)
    End Function



    ''' <summary>
    ''' 获取Custom1最后更新的时间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom1LastUpdate() As String
        GetCustom1LastUpdate = GetLastUpdate(tagHFMDIMENSIONS.DIMENSIONCUSTOM1)
    End Function


    ''' <summary>
    ''' 获取Custom2最后更新的时间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom2LastUpdate() As String
        GetCustom2LastUpdate = GetLastUpdate(tagHFMDIMENSIONS.DIMENSIONCUSTOM2)
    End Function



    ''' <summary>
    ''' 获取Custom3最后更新的时间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom3LastUpdate() As String
        GetCustom3LastUpdate = GetLastUpdate(tagHFMDIMENSIONS.DIMENSIONCUSTOM3)
    End Function


    ''' <summary>
    ''' 获取Custom4最后更新的时间
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCustom4LastUpdate() As String
        GetCustom4LastUpdate = GetLastUpdate(tagHFMDIMENSIONS.DIMENSIONCUSTOM4)
    End Function

    ''' <summary>
    ''' 
    ''' Returns the value of the FDM Application Name setting for the application.
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetAppName()
        Dim sAppName As String = DirectCast(cSession.SystemInfo, HsvSystemInfo).GetApplicationName()
        GetAppName = sAppName
    End Function

    ''' <summary>
    ''' 获取所有的日记帐组
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetJournalGroup() As String

        Dim IHsJourEx As HsvJournals = cSession.Journals
        Dim index As Integer = -1
        Dim Desc As String() = Nothing
        Dim Str As StringBuilder = New StringBuilder
        Dim Vals As String() = Nothing

        DirectCast(IHsJourEx, IHsvJournalsEx).EnumJournalGroups(Vals, Desc)

        If Not (Vals Is Nothing) Then
            For index = LBound(Vals) To UBound(Vals)
                ' TODO 只用到了 Vals, 但是没有用到 Desc，是否需要对接口进一步封装
                If Not (String.IsNullOrEmpty(Vals(index).Trim().ToString())) Then
                    Str.Append(CStr(Vals(index)))
                    Str.Append(vbCr + vbLf)
                End If
            Next (index)
        End If

        ' TODO 返回的结果中都带用户、应用名称、更新时间，这里用的是GetCustom3LastUpdate，是否需要修改
        GetJournalGroup = GetUsername() + vbCr + vbLf + GetAppName() + vbCr + vbLf + GetCustom3LastUpdate() + vbCr + vbLf + Str.ToString()
    End Function


    ''' <summary>
    ''' 获取指定单元格的数据状态
    ''' </summary>
    ''' <param name="Scenario"></param>
    ''' <param name="Year"></param>
    ''' <param name="Period"></param>
    ''' <param name="View"></param>
    ''' <param name="Entity"></param>
    ''' <param name="Parent"></param>
    ''' <param name="Value"></param>
    ''' <param name="Account"></param>
    ''' <param name="ICP"></param>
    ''' <param name="Custom1"></param>
    ''' <param name="Custom2"></param>
    ''' <param name="Custom3"></param>
    ''' <param name="Custom4"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetCell(ByVal Scenario As Long, ByVal Year As Long, ByVal Period As Long, ByVal View As Long, ByVal Entity As Long, ByVal Parent As Long, ByVal Value As Long, ByVal Account As Long, _
     ByVal ICP As Long, ByVal Custom1 As Long, ByVal Custom2 As Long, ByVal Custom3 As Long, ByVal Custom4 As Long) As String
        Dim pdData As Double = -1
        Dim plStatus As VariantType
        Dim c_Data = cSession.Data

        Try
            ' TODO 这里取了值和状态，最终返回了状态，这个方法是给谁用的
            c_Data.GetCell(Scenario, Year, Period, View, Entity, Parent, Value, Account, ICP, Custom1, Custom2, Custom3, Custom4, pdData, plStatus)

            ' TODO tagCALCSTATUSHIGHBITS 的枚举范围　
            Dim Result As StringBuilder = New StringBuilder()
            For Each status As tagCALCSTATUSHIGHBITS In [Enum].GetValues(GetType(tagCALCSTATUSHIGHBITS))
                If plStatus And status Then
                    Result.Append(status.ToString())
                End If
            Next

            ' TODO tagCALCSTATUSMIDDLEBITS 的枚举范围　
            For Each status As tagCALCSTATUSMIDDLEBITS In [Enum].GetValues(GetType(tagCALCSTATUSMIDDLEBITS))
                If plStatus And status Then
                    Result.Append(status.ToString())
                End If
            Next

            ' TODO tagCALCSTATUSLOWBITS 的枚举范围　
            For Each status As tagCALCSTATUSLOWBITS In [Enum].GetValues(GetType(tagCALCSTATUSLOWBITS))
                If plStatus And status Then
                    Result.Append(status.ToString())
                End If
            Next

            ' TODO 取出的状态，只会有一个值，还是会有多个值，状态中没有分隔符，如何区分
            GetCell = Result.ToString()

        Catch ex As Exception

            GetCell = "CELLSTATUS_INVALID"
        End Try
    End Function

    ''' <summary>
    ''' 获取成员的ID
    ''' </summary>
    ''' <param name="lDimID"></param>
    ''' <param name="sMemLabel"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetMemberID(ByVal lDimID As Long, ByVal sMemLabel As String) As Long
        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim cTreeInfo As IHsvTreeInfo = cMetadata.Dimension(lDimID)

        GetMemberID = DirectCast(cTreeInfo, IHsvTreeInfo).GetItemID(sMemLabel)
    End Function


    ''' <summary>
    ''' 写日志接口
    ''' 
    ''' TODO 现在在什么情况，没有在用了
    ''' </summary>
    ''' <param name="Log"></param>
    ''' <remarks></remarks>
    Private Sub writeLog(ByVal Log As String)
        ' TODO 是否需要日志
    End Sub



    ''' <summary>
    ''' TODO 这个方法是哪里用的
    ''' </summary>
    ''' <param name="Scenario"></param>
    ''' <param name="Year"></param>
    ''' <param name="Period"></param>
    ''' <param name="View"></param>
    ''' <param name="Entity"></param>
    ''' <param name="Parent"></param>
    ''' <param name="Value"></param>
    ''' <param name="Account"></param>
    ''' <param name="ICP"></param>
    ''' <param name="Custom1"></param>
    ''' <param name="Custom2"></param>
    ''' <param name="Custom3"></param>
    ''' <param name="Custom4"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Validate(ByVal Scenario As String, ByVal Year As String, ByVal Period As String, ByVal View As String, ByVal Entity As String, ByVal Parent As String, ByVal Value As String, ByVal Account As String, _
     ByVal ICP As String, ByVal Custom1 As String, ByVal Custom2 As String, ByVal Custom3 As String, ByVal Custom4 As String) As String
        Dim lScenario As Long, lYear As Long, lPeriod As Long, lView As Long, lEntity As Long, lParent As Long, lValue As Long, lAccount As Long, lICP As Long, lCustom1 As Long, lCustom2 As Long, lCustom3 As Long, lCustom4 As Long
        lScenario = GetMemberID(tagHFMDIMENSIONS.DIMENSIONSCENARIO, Scenario)
        lYear = GetMemberID(tagHFMDIMENSIONS.DIMENSIONYEAR, Year)
        lPeriod = GetMemberID(tagHFMDIMENSIONS.DIMENSIONPERIOD, Period)
        lEntity = GetMemberID(tagHFMDIMENSIONS.DIMENSIONENTITY, Entity)
        lParent = GetMemberID(tagHFMDIMENSIONS.DIMENSIONENTITY, Parent)
        lAccount = GetMemberID(tagHFMDIMENSIONS.DIMENSIONACCOUNT, Account)
        lValue = GetMemberID(tagHFMDIMENSIONS.DIMENSIONVALUE, Value)
        lView = GetMemberID(tagHFMDIMENSIONS.DIMENSIONVIEW, View)
        lICP = GetMemberID(tagHFMDIMENSIONS.DIMENSIONICP, ICP)
        lCustom1 = GetMemberID(tagHFMDIMENSIONS.DIMENSIONCUSTOM1, Custom1)
        lCustom2 = GetMemberID(tagHFMDIMENSIONS.DIMENSIONCUSTOM2, Custom2)
        lCustom3 = GetMemberID(tagHFMDIMENSIONS.DIMENSIONCUSTOM3, Custom3)
        lCustom4 = GetMemberID(tagHFMDIMENSIONS.DIMENSIONCUSTOM4, Custom4)
        Validate = GetCell(lScenario, lYear, lPeriod, lView, lEntity, lParent, lValue, lAccount, lICP, lCustom1, lCustom2, lCustom3, lCustom4)

    End Function


    ''' <summary>
    ''' TODO 为C#返回VBCrLf, 这个是在干吗，使用\r\n不行吗？
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function ReturnVBCrLf()
        ReturnVBCrLf = vbCrLf
    End Function


    ''' <summary>
    ''' 检查维度组合是否有效
    ''' </summary>
    ''' <param name="Str"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckDimensionValidate(ByVal Str As String)
        Dim Dimension() As String = Split(Str, ";")
        Dim ErrorMsg As String = ""

        ' 检查ICP有效性
        Try
            If CheckICPValidate(Dimension(2), Dimension(3)) = False Then
                ErrorMsg = "Error:#ICP#" + Dimension(3) + vbCrLf + FormatErrDimension(Str)
            End If
        Catch ex As Exception
            ErrorMsg = "Error:#ICP#" + Dimension(3) + vbCrLf + FormatErrDimension(Str)
        End Try

        ' 检查Custom1有效性
        Try
            If CheckCustom1Validate(Dimension(2), Dimension(4)) = False Then
                ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom1#" + Dimension(4) + vbCrLf + FormatErrDimension(Str)
            End If
        Catch ex As Exception
            ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom1#" + Dimension(4) + vbCrLf + FormatErrDimension(Str)
        End Try

        ' 检查Custom2有效性
        Try
            If CheckCustom2Validate(Dimension(2), Dimension(5)) = False Then
                ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom2#" + Dimension(5) + vbCrLf + FormatErrDimension(Str)
            End If
        Catch ex As Exception
            ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom2#" + Dimension(5) + vbCrLf + FormatErrDimension(Str)
        End Try

        ' 检查Custom3有效性
        Try
            If CheckCustom3Validate(Dimension(2), Dimension(6)) = False Then
                ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom3#" + Dimension(6) + vbCrLf + FormatErrDimension(Str)

            End If
        Catch ex As Exception
            ErrorMsg = ErrorMsg + vbCrLf + "Error:#Custom3#" + Dimension(6) + vbCrLf + FormatErrDimension(Str)
        End Try

        ' TODO 格式化错误信息，这个是在干吗？
        If Not String.IsNullOrEmpty(ErrorMsg.Trim()) Then
            ErrorMsg = vbCrLf + ErrorMsg
        End If

        CheckDimensionValidate = ErrorMsg
    End Function



    ''' <summary>
    ''' 还原出错日记账数据
    ''' 多体日记账:d;<parent.entity>;<account>;<ICP>;<C1>;<C2>;<C3>;<C4>;<amount type>;<value>
    ''' 单体日记账:s;<entity>;<account>;<ICP>;<C1>;<C2>;<C3>;<C4>;<amount type>;<amount>;<value>
    ''' </summary>
    ''' <param name="Str"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function FormatErrDimension(ByVal Str As String)
        Dim Dimension As String() = Split(Str, ";")
        Dim i As Integer = -1
        Dim temp As StringBuilder = New StringBuilder

        If Dimension(0).ToString() = "s" Then
            ' 如果是单体日记帐
            For i = 2 To UBound(Dimension) - 2

                temp.Append(Dimension(i).ToString())
                temp.Append(";")
            Next i

        Else
            ' 如果是多体日记帐
            For i = 1 To UBound(Dimension) - 2

                temp.Append(Dimension(i).ToString())
                temp.Append(";")

            Next i
        End If

        ' TODO 这个返回了要干吗
        FormatErrDimension = temp.ToString()
    End Function


    ''' <summary>
    ''' 检查权限并返回验证结果
    ''' </summary>
    ''' <param name="sScenario"></param>
    ''' <param name="sYear"></param>
    ''' <param name="sPeriod"></param>
    ''' <param name="sEntity"></param>
    ''' <param name="sParent"></param>
    ''' <param name="sValue"></param>
    ''' <param name="sAccount"></param>
    ''' <param name="sICP"></param>
    ''' <param name="sCustom1"></param>
    ''' <param name="sCustom2"></param>
    ''' <param name="sCustom3"></param>
    ''' <param name="sCustom4"></param>
    ''' <param name="priority"></param>
    ''' <param name="Journals"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CheckSecurityResult(ByVal sScenario As String, ByVal sYear As String, ByVal sPeriod As String,
                           ByVal sEntity As String, ByVal sParent As String, ByVal sValue As String, ByVal sAccount As String, ByVal sICP As String,
                           ByVal sCustom1 As String, ByVal sCustom2 As String, ByVal sCustom3 As String, ByVal sCustom4 As String,
                           ByVal priority As Integer, ByVal Journals As String)

        Dim ErrorMsg As String = "", entity As String = ""

        If sEntity.Contains(".") Then
            entity = sEntity.Split(".")(1)
        Else
            entity = sEntity
        End If

        If CheckSecurity(sScenario, sYear, sPeriod, entity, sParent, sValue, sAccount, sICP, sCustom1, sCustom2, sCustom3, sCustom4, priority) = False Then
            ErrorMsg = vbCrLf + "Error:#Permission#" + vbCrLf + FormatErrDimension(Journals) + vbCrLf
        End If

        CheckSecurityResult = ErrorMsg
    End Function

    ''' <summary>
    ''' 验证Account和ICP的组合是否有效
    ''' </summary>
    ''' <param name="sAccount"></param>
    ''' <param name="sICP"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CheckICPValidate(ByVal sAccount As String, ByVal sICP As String)
        Dim funEndTime, funResult As String
        Dim FunName As String = String.Format("CheckICPValidate({0},{1})", sAccount, sICP)
        Dim funStarTime As String = DateTime.Now.ToString()

        Try
            If sAccount <> "0" And sICP <> "0" And (Not String.IsNullOrEmpty(sICP)) Then

                Dim cHsvAccounts As HsvAccounts
                Dim cTreeInfo As IHsvTreeInfo, lAcct As Long, Result As Boolean, lICP As Long
                Dim bIsValid As Boolean
                Dim cMetadata As HsvMetadata
                cMetadata = cSession.Metadata
                cHsvAccounts = cMetadata.Accounts
                'cMetadata is an HsvMetadata object reference
                cTreeInfo = cMetadata.Accounts
                lAcct = cTreeInfo.GetItemID(sAccount)
                cHsvAccounts.IsICP(lAcct, bIsValid)

                cTreeInfo = cMetadata.ICPs
                lICP = cTreeInfo.GetItemID(sICP)

                funEndTime = DateTime.Now.ToString()

                If lAcct < 0 Or lICP < 0 Then
                    Result = False
                ElseIf bIsValid = False And sICP <> "[ICP None]" Then
                    Result = False
                Else
                    Result = True
                End If
                funResult = Result.ToString()
                'Log = coms.SetEntity(GetUsername().ToString(), FunName, funStarTime, funEndTime, funResult, Nothing)
                'writeLog(Log)
                CheckICPValidate = Result
            Else
                CheckICPValidate = False
            End If

        Catch ex As Exception
            CheckICPValidate = False
        End Try
    End Function


    ''' <summary>
    ''' 验证Account和Custom1的组合是否有效
    ''' </summary>
    ''' <param name="sAccount"></param>
    ''' <param name="sCustom1"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckCustom1Validate(ByVal sAccount As String, ByVal sCustom1 As String) As Boolean
        Dim funResult As Boolean

        Try
            ' TODO 这段判断的业务含义是什么？
            If sAccount <> "0" And sCustom1 <> "0" And (Not String.IsNullOrEmpty(sCustom1)) Then
                Dim cMetadata As HsvMetadata = cSession.Metadata

                ' 取Account ID
                Dim cTreeInfo As IHsvTreeInfo = cMetadata.Accounts
                Dim lAcct As Long = cTreeInfo.GetItemID(sAccount)

                ' 取Custom1 ID
                cTreeInfo = cMetadata.Custom1
                Dim lCustom1 As Long = cTreeInfo.GetItemID(sCustom1)

                ' 判断Account和Custom1的有效性
                Dim bIsValid As Boolean
                cMetadata.IsCustomMemberValidForAccount(tagHFMDIMENSIONS.DIMENSIONCUSTOM1, lCustom1, lAcct, bIsValid)

                funResult = (bIsValid = True And lAcct >= 0 And lCustom1 >= 0)

            Else
                funResult = False
            End If
        Catch ex As Exception
            funResult = False
        End Try

        CheckCustom1Validate = funResult
    End Function


    ''' <summary>
    ''' 验证Account和Custom2的组合是否有效
    ''' 
    ''' TODO 整改方法，与Account和Custom1合并
    ''' </summary>
    ''' <param name="sAccount"></param>
    ''' <param name="sCustom2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckCustom2Validate(ByVal sAccount As String, ByVal sCustom2 As String) As Boolean
        Dim funResult As Boolean

        Try
            ' TODO 这段判断的业务含义是什么？
            If sAccount <> "0" And sCustom2 <> "0" And (Not String.IsNullOrEmpty(sCustom2)) Then
                Dim cMetadata As HsvMetadata = cSession.Metadata

                ' 取Account ID
                Dim cTreeInfo As IHsvTreeInfo = cMetadata.Accounts
                Dim lAcct As Long = cTreeInfo.GetItemID(sAccount)

                ' 取Custom1 ID
                cTreeInfo = cMetadata.Custom2
                Dim lCustom2 As Long = cTreeInfo.GetItemID(sCustom2)

                ' 判断Account和Custom1的有效性
                Dim bIsValid As Boolean
                cMetadata.IsCustomMemberValidForAccount(tagHFMDIMENSIONS.DIMENSIONCUSTOM2, lCustom2, lAcct, bIsValid)

                funResult = (bIsValid = True And lAcct >= 0 And lCustom2 >= 0)

            Else
                funResult = False
            End If
        Catch ex As Exception
            funResult = False
        End Try

        CheckCustom2Validate = funResult

    End Function



    ''' <summary>
    ''' 验证Account和Custom3的组合是否有效
    ''' 
    ''' TODO 整改方法，与Account和Custom1合并
    ''' </summary>
    ''' <param name="sAccount"></param>
    ''' <param name="sCustom3"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CheckCustom3Validate(ByVal sAccount As String, ByVal sCustom3 As String) As Boolean
        Dim funResult As Boolean

        Try
            ' TODO 这段判断的业务含义是什么？
            If sAccount <> "0" And sCustom3 <> "0" And (Not String.IsNullOrEmpty(sCustom3)) Then
                Dim cMetadata As HsvMetadata = cSession.Metadata

                ' 取Account ID
                Dim cTreeInfo As IHsvTreeInfo = cMetadata.Accounts
                Dim lAcct As Long = cTreeInfo.GetItemID(sAccount)

                ' 取Custom1 ID
                cTreeInfo = cMetadata.Custom3
                Dim lCustom3 As Long = cTreeInfo.GetItemID(sCustom3)

                ' 判断Account和Custom1的有效性
                Dim bIsValid As Boolean
                cMetadata.IsCustomMemberValidForAccount(tagHFMDIMENSIONS.DIMENSIONCUSTOM3, lCustom3, lAcct, bIsValid)

                funResult = (bIsValid = True And lAcct >= 0 And lCustom3 >= 0)

            Else
                funResult = False
            End If
        Catch ex As Exception
            funResult = False
        End Try

        CheckCustom3Validate = funResult
    End Function


    ''' <summary>
    ''' 格式化NO Input 错
    ''' TODO 这个是在干吗，要整改掉
    ''' </summary>
    ''' <param name="err"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function NoInputErrMsg(ByVal err As String) As String
        NoInputErrMsg = vbLf + "Error:#NOINPUT#" + vbCrLf + FormatErrDimension(err) + vbCrLf
    End Function


    ''' <summary>
    ''' 获取Scenario维度所有成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetScenarios(ByVal sLanguage As String) As String
        Dim cMetadata As HsvMetadata = cSession.Metadata
        GetScenarios = GetMemberList(sLanguage, cMetadata.Scenarios, False)
    End Function


    ''' <summary>
    ''' 获取Entity维度所有成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetEntitiesEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata
        GetEntitiesEx = GetMemberListEx(sLanguage, cMetadata.Entities, True)
    End Function

    ''' <summary>
    ''' 获取Account维度所有的成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetAccountsEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata
        GetAccountsEx = GetMemberListEx(sLanguage, cMetadata.Accounts, False)
    End Function


    ''' <summary>
    ''' 获取ICP维度所有的成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetICPsEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata
        GetICPsEx = GetMemberListEx(sLanguage, cMetadata.ICPs, False)
    End Function


    ''' <summary>
    ''' 获取Year维度所有的成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetYearsEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetYearsEx = GetMemberListEx(sLanguage, cMetadata.Years, False)
    End Function


    ''' <summary>
    ''' 获取Period维度所有的成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPeriodsEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetPeriodsEx = GetMemberListEx(sLanguage, cMetadata.Periods, False)
    End Function


    ''' <summary>
    ''' 获取Scenario维度所有的成员
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetScenariosEx(ByVal sLanguage As String) As List(Of MetaItem)
        Dim cMetadata As HsvMetadata = cSession.Metadata

        GetScenariosEx = GetMemberListEx(sLanguage, cMetadata.Scenarios, False)
    End Function


    ''' <summary>
    ''' 获取扩展分析模板
    ''' 
    ''' TODO 这个方法在 11.1.2.2的环境上不能用，什么情况？
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetExtendedAnalyticTemplates() As List(Of MetaItem)
        ' 使用HFMwStarSchema来操作模板
        Dim cStarSchema As HFMwStarSchema = New HFMwStarSchema
        cStarSchema.SetWebSession(cWebSession)

        ' TODO 获取当前的用户名，应该是一个独立的方法
        Dim sUsername As String = ""
        DirectCast(cSession.SystemInfo, HsvSystemInfo).GetUserName(sUsername)

        ' 获取所有的模板, ShortName = 模板名称, FullName = UserName.模板名称, Description = UserName.模板名称
        Dim aResult As List(Of MetaItem) = New List(Of MetaItem)
        For Each sTemplate As String In cStarSchema.EnumTemplates()
            Dim cItem As MetaItem = New MetaItem
            cItem.ShortName = sTemplate
            cItem.FullName = String.Format("{0}.{1}", sUsername, sTemplate)
            cItem.Description = String.Format("{0}.{1}", sUsername, sTemplate)

            aResult.Add(cItem)
        Next

        ' 结果返回　
        GetExtendedAnalyticTemplates = aResult
    End Function

    ''' <summary>
    ''' 获取Entity的详细信息
    ''' TODO 这个方法是提供给EAL程序使用
    ''' </summary>
    ''' <param name="sLanguage"></param>
    ''' <param name="sScenario"></param>
    ''' <param name="sYear"></param>
    ''' <param name="sPeriod"></param>
    ''' <param name="sValue"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetEntitiesDetail(ByVal sLanguage As String, ByVal sScenario As String, ByVal sYear As String, ByVal sPeriod As String, ByVal sValue As String) As List(Of MetaItem)
        ' 获取所有的Entity对象
        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim cSecurityAccess As IHsvDataSecurity = cSession.Security
        Dim aResult As List(Of MetaItem) = GetEntitiesEx(sLanguage)

        ' 遍历Entity对象，获取ReviewLevel状态　
        For Each cItem As MetaItem In aResult
            Dim security As Integer, flow As Short
            cSecurityAccess.GetProcessUnitAccessRightsAndState(DirectCast(cMetadata.Scenarios, IHsvTreeInfo).GetItemID(sScenario), _
                                                                DirectCast(cMetadata.Years, IHsvTreeInfo).GetItemID(sYear), _
                                                                DirectCast(cMetadata.Periods, IHsvTreeInfo).GetItemID(sPeriod), _
                                                                DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(cItem.ShortName), _
                                                                DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(cItem.FullName.Split(".")(0)), _
                                                                DirectCast(cMetadata.Values, IHsvTreeInfo).GetItemID(sValue), _
                                                                security, flow)
            ' TODO　为什么给 String类型返回　
            cItem.Attribute = flow.ToString()
        Next

        GetEntitiesDetail = aResult
    End Function


    ''' <summary>
    ''' 获取流程状态
    ''' TODO 这个可以和上面的方法合并 GetEntitiesDetail
    ''' </summary>
    ''' <param name="sScenario"></param>
    ''' <param name="sYear"></param>
    ''' <param name="sPeriod"></param>
    ''' <param name="sValue"></param>
    ''' <param name="sEntity"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetProcessLevel(ByVal sScenario As String, ByVal sYear As String, ByVal sPeriod As String, ByVal sValue As String, ByVal sEntity As String) As Short

        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim cSecurityAccess As IHsvDataSecurity = cSession.Security
        Dim hsvEntities As IHsvTreeInfo = DirectCast(cMetadata.Entities, IHsvTreeInfo)

        Dim varParents As Object = Nothing
        hsvEntities.EnumParents(hsvEntities.GetItemID(sEntity), varParents)

        Dim sMaxID As Integer = 0

        For index As Integer = LBound(varParents) To UBound(varParents)

            Dim security As Integer, flow As Short
            cSecurityAccess.GetProcessUnitAccessRightsAndState(DirectCast(cMetadata.Scenarios, IHsvTreeInfo).GetItemID(sScenario), _
                                                                DirectCast(cMetadata.Years, IHsvTreeInfo).GetItemID(sYear), _
                                                                DirectCast(cMetadata.Periods, IHsvTreeInfo).GetItemID(sPeriod), _
                                                                DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(sEntity), _
                                                                varParents(index), _
                                                                DirectCast(cMetadata.Values, IHsvTreeInfo).GetItemID(sValue), _
                                                                security, flow)

            If sMaxID < flow Then
                sMaxID = flow
            End If
        Next index

        GetProcessLevel = sMaxID
    End Function

    ''' <summary>
    ''' 获取流程状态
    ''' TODO 这个可以和上面的方法合并 GetEntitiesDetail
    ''' </summary>
    ''' <param name="sScenario"></param>
    ''' <param name="sYear"></param>
    ''' <param name="sPeriod"></param>
    ''' <param name="sValue"></param>
    ''' <param name="sEntity"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetProcessLevelEx(ByVal sScenario As String, ByVal sYear As String, ByVal sPeriod As String, ByVal sValue As String, ByVal sEntity As String, ByVal nPhase As Integer) As Short

        Dim cMetadata As HsvMetadata = cSession.Metadata
        Dim cSecurityAccess As IHsvDataSecurity = cSession.Security
        Dim hsvEntities As IHsvTreeInfo = DirectCast(cMetadata.Entities, IHsvTreeInfo)

        Dim varParents As Object = Nothing
        hsvEntities.EnumParents(hsvEntities.GetItemID(sEntity), varParents)

        Dim sMaxID As Integer = 0

        For index As Integer = LBound(varParents) To UBound(varParents)

            Dim security As Integer, flow As Short
            cSecurityAccess.GetProcessUnitAccessRightsAndStateEx(DirectCast(cMetadata.Scenarios, IHsvTreeInfo).GetItemID(sScenario), _
                                                                DirectCast(cMetadata.Years, IHsvTreeInfo).GetItemID(sYear), _
                                                                DirectCast(cMetadata.Periods, IHsvTreeInfo).GetItemID(sPeriod), _
                                                                DirectCast(cMetadata.Entities, IHsvTreeInfo).GetItemID(sEntity), _
                                                                varParents(index), _
                                                                DirectCast(cMetadata.Values, IHsvTreeInfo).GetItemID(sValue), _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                HFMConstantsLib.tagPOVDEFAULTS.MEMBERNOTUSED, _
                                                                nPhase, _
                                                                security, flow)

            If sMaxID < flow Then
                sMaxID = flow
            End If
        Next index

        GetProcessLevelEx = sMaxID
    End Function


    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="sTextFile"></param>
    ''' <param name="sLogfile"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function LoadData(ByVal sTextFile As String, ByVal sLogfile As String) As String
        ' 使用 HsvcDataLoad 对象进行数据加载
        Dim cHsvcDataLoad As HsvcDataLoad = New HsvcDataLoad
        cHsvcDataLoad.SetSession(cSession)

        ' 设置加载选项为 Load, Replace
        Dim cOptions As HsvcDataLoadLib.IHsvLoadExtractOptions = cHsvcDataLoad.LoadOptions
        cOptions.Item(HSV_DATALOAD_OPTION.HSV_DATALOAD_OPT_MODE).CurrentValue = HSV_DATALOAD_MODES.HSV_DATALOAD_LOAD
        cOptions.Item(HSV_DATALOAD_OPTION.HSV_DATALOAD_OPT_DUPLICATES).CurrentValue = HSV_DATALOAD_DUPLICATE_OPTIONS.HSV_DATALOAD_MERGE

        ' 加载数据
        cHsvcDataLoad.Load(sTextFile, sLogfile)

        LoadData = ""
    End Function

    ''' <summary>
    ''' 获取模板列表, 使用HFMwStartSchema
    ''' 
    ''' TODO 这个是为了验证11.1.2.2不能用的问题来测试的
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function EnumTemplates() As Object()

        Dim cStarSchema As HFMwStarSchema = New HFMwStarSchema
        cStarSchema.SetWebSession(cWebSession)

        Dim result() As Object = cStarSchema.EnumTemplates()

        EnumTemplates = result
    End Function


    ''' <summary>
    ''' 获取模板列表, 使用HsvStarSchemaACM
    ''' 
    ''' TODO 这个是为了验证11.1.2.2不能用的问题来测试的
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function EnumTemplates2() As Object()
        Dim cStarSchema As HsvStarSchemaACM = New HsvStarSchemaACM
        cStarSchema.SetSession(cWebSession.session)

        EnumTemplates2 = DirectCast(cStarSchema, IHsvStarSchemaTemplates).EnumTemplates()
    End Function


    ''' <summary>
    ''' 创建星形架构
    ''' </summary>
    ''' <param name="sTemplate"></param>
    ''' <param name="ePushOption"></param>
    ''' <param name="sScenario"></param>
    ''' <param name="sYear"></param>
    ''' <param name="sPeriod"></param>
    ''' <param name="sEntities"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CreateStarSchema(ByVal sTemplate As String, ByVal ePushOption As HFMConstantsLib.SS_PUSH_OPTIONS,
                                ByVal sScenario As String, ByVal sYear As String,
                                ByVal sPeriod As String, ByVal sEntities As String) As String
        ' 获取指定的模板
        Dim cStarSchema As HFMwStarSchema = New HFMwStarSchema
        cStarSchema.SetWebSession(cWebSession)
        Dim sXMLSetting As String = cStarSchema.GetTemplate(sTemplate)

        ' 加载模板到XML对象中　
        Dim elmDom As DOMDocument60 = New DOMDocument60
        elmDom.setProperty("NewParser", True)
        elmDom.async = False
        elmDom.loadXML(sXMLSetting)

        ' 从XML中初始化POVBar对象
        Dim cPOVBar As POVBar = New POVBar
        Dim cOptPanel As OptionsPanel = New OptionsPanel
        cPOVBar.m_mbrselxml.setWebSession(cWebSession)
        cPOVBar.initFromXML(elmDom)
        cOptPanel.initFromXML(elmDom)

        ' 构建saaMembers数组
        Dim ndx As Integer, saaMembers()() As String
        Dim mbrselxml As HFMwMbrSel = cPOVBar.MbrSelXml
        saaMembers = New String(tagHFMDIMENSIONS.DIMENSIONCUSTOM4)() {}
        For ndx = tagHFMDIMENSIONS.DIMENSIONSCENARIO To tagHFMDIMENSIONS.DIMENSIONCUSTOM4
            saaMembers(ndx) = expandListIfNecessary(mbrselxml.AttrDim(ndx, tagWEBOM_MBRSEL_IDS.WEBOM_MBRSEL_ID_VALUE))
        Next
        saaMembers(tagHFMDIMENSIONS.DIMENSIONSCENARIO) = expandListIfNecessary(sScenario)
        saaMembers(tagHFMDIMENSIONS.DIMENSIONYEAR) = expandListIfNecessary(sYear)
        saaMembers(tagHFMDIMENSIONS.DIMENSIONPERIOD) = expandListIfNecessary(sPeriod)
        saaMembers(tagHFMDIMENSIONS.DIMENSIONENTITY) = expandListIfNecessary(sEntities)

        ' 创建星形架构
        cStarSchema.CreateStarSchema(cOptPanel.SelectedDSN, cOptPanel.TablePrefix, ePushOption, _
                                        cOptPanel.ExportOption, cOptPanel.ExcludeDynamicAccts, _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONSCENARIO), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONYEAR), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONPERIOD), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONVIEW), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONENTITY), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONVALUE), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONACCOUNT), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONICP), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONCUSTOM1), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONCUSTOM2), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONCUSTOM3), _
                                        saaMembers(tagHFMDIMENSIONS.DIMENSIONCUSTOM4))

        ' TODO 这里返回了一个值，为什么用TablePrefix
        CreateStarSchema = cOptPanel.TablePrefix
    End Function


    ''' <summary>
    ''' 展开字符串到数组
    ''' </summary>
    ''' <param name="selValue"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function expandListIfNecessary(ByRef selValue As String) As String()
        Dim saSelectedMembers As String(), ndx As Integer

        ' 如果没有选择，则默认为ALL
        If Len(selValue) <= 0 Then
            selValue = "ALL"
        End If

        ' 展开后Trim
        saSelectedMembers = Split(selValue, ";")
        For ndx = LBound(saSelectedMembers) To UBound(saSelectedMembers)
            saSelectedMembers(ndx) = Trim(saSelectedMembers(ndx))
        Next

        expandListIfNecessary = saSelectedMembers
    End Function

    ''' <summary>
    ''' 用于检查扩展分析的执行情况
    ''' TODO 这个方法目前不能使用
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function CheckStatus()
        Dim m_strServername As String             ' Server name from request
        Dim m_strUserName As String               ' User name from request
        Dim m_lTask As Long                     ' Task name code
        Dim m_lStatus As Long                   ' Task status code
        Dim m_bAllServers As Boolean               ' Flag to search for all servers
        Dim m_bAllSessions As Boolean              ' Flag to search for all sessions
        Dim m_bAllUsers As Boolean                ' Flag to search for all users
        Dim m_bAllTasks As Boolean                 ' Flag to search for all tasks
        Dim m_bAllStatus As Boolean                ' Flag to search for all status
        Dim m_lStartIndex As Long               ' Start index of task list to display
        Dim m_lEndIndex As Long                ' End index of task list to display
        Dim m_laTaskIDs As Long()                ' Task ID array
        Dim m_laTaskTypes As Long()               ' Task type array
        Dim m_laTaskProgresses As Long()         ' Task progress array
        Dim m_laTaskStatuses As Long()           ' Task status array
        Dim m_straServerNames As String()         ' Server name array
        Dim m_straUserNames As String()            ' User name array
        Dim m_straDescriptions As String()          ' Description array
        Dim m_baStopTaskFlags As Boolean()
        Dim m_straLogs As String()                  ' Logs array
        Dim m_daStartTimes As DateTime()              ' Start times array
        Dim m_daStartRunningTimes As DateTime()      ' Start Running times array
        Dim m_daLastUpdateTimes As DateTime()        ' Last update times array
        Dim m_lTotalRecordsInDatabase As Long  ' Total records in database

        Dim cSystemInfo As HFMwSystemInfo


        m_bAllTasks = False
        m_lTask = tagUSERACTIVITYCODE.USERACTIVITYCODE_EA_EXPORT
        m_bAllUsers = True
        m_bAllServers = True
        m_bAllSessions = True
        m_bAllStatus = True
        m_lStartIndex = 0
        m_lEndIndex = 2
        m_strUserName = ""
        m_strServername = ""
        m_laTaskIDs = New Long() {}
        m_laTaskTypes = New Long() {}
        m_laTaskProgresses = New Long() {}
        m_laTaskStatuses = New Long() {}
        m_straUserNames = New String() {}
        m_straServerNames = New String() {}
        m_daStartTimes = New DateTime() {}
        m_daStartRunningTimes = New DateTime() {}
        m_daLastUpdateTimes = New DateTime() {}
        m_straDescriptions = New String() {}
        m_baStopTaskFlags = New Boolean() {}
        m_straLogs = New String() {}


        cSystemInfo = New HFMwSystemInfo()
        cSystemInfo.SetWebSession(cWebSession)
        m_lTotalRecordsInDatabase = cSystemInfo.EnumRunningTasksEx( _
                                            m_bAllTasks, m_lTask, _
                                            m_bAllUsers, m_strUserName, _
                                            m_bAllServers, m_strServername, _
                                            m_bAllSessions, _
                                            m_bAllStatus, m_lStatus, _
                                            m_lStartIndex, m_lEndIndex, _
                                            m_laTaskIDs, m_laTaskTypes, _
                                            m_laTaskProgresses, m_laTaskStatuses, _
                                            m_straUserNames, m_straServerNames, _
                                            m_daStartTimes, m_daStartRunningTimes, m_daLastUpdateTimes, _
                                            m_straDescriptions, m_baStopTaskFlags, m_straLogs)


        If m_lTotalRecordsInDatabase < 1 Then
            CheckStatus = -1
        Else
            CheckStatus = m_laTaskStatuses(0)
        End If
    End Function
End Class



''' <summary>
''' POVBar 辅助类用于扩展分析
''' 
''' TODO 分析这个类，将其整合到Extend Analysis中
''' </summary>
''' <remarks></remarks>
Class POVBar                            ' prefix povdisp

    Const EA_POV = "povEA"
    Public m_mbrselxml As HFMwMbrSel                 ' MbrSel XML object

    Public ReadOnly Property MbrSelXml
        Get
            Return m_mbrselxml
        End Get
    End Property

    Public Sub New()
        m_mbrselxml = New HFMwMbrSel
    End Sub

    ''' <summary>
    ''' 从XML 中反向出POV对象
    ''' 
    ''' TODO XML的结构
    ''' 
    ''' </summary>
    ''' <param name="xmlNode"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function initFromXML(ByRef xmlNode As DOMDocument60) As Boolean
        Dim xmlPOV As IXMLDOMNode
        initFromXML = False

        If xmlNode Is Nothing Then Exit Function

        xmlPOV = xmlNode.selectSingleNode("//" & EA_POV)

        If xmlPOV Is Nothing Then Exit Function
        If m_mbrselxml Is Nothing Then Exit Function

        If (Not xmlPOV Is Nothing) Then
            m_mbrselxml.ScriptString = xmlPOV.text
        End If

        initFromXML = True
    End Function

End Class


''' <summary>
''' 扩展分析辅助类
''' 
''' TODO 整合到Extend Analysis中
''' </summary>
''' <remarks></remarks>
Class OptionsPanel                      'prefix optpanel

    Const EA_OPTIONS = "options"
    Const EA_SELECTED_DSN = "selectedDSN"
    Const EA_EXPORT_OPTION = "exportOption"
    Const EA_TABLE_PREFIX = "tablePrefix"
    Const EA_EXCLUDE_DYN_ACCTS = "excludeDynAccts"

    Public Property ExportOption As Long            ' Aggregation option for export
    Public Property TablePrefix As String            ' Prefix for the table name
    Public Property SelectedDSN As String           ' DSN Selected
    Public Property ExcludeDynamicAccts As Boolean      ' Flag to exclude dynamic accounts from export


    ''' <summary>
    ''' 从XML中反向于POV和选项
    ''' </summary>
    ''' <param name="xmlNode"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function initFromXML(ByRef xmlNode As DOMDocument60) As Boolean
        Dim xmlOptions As IXMLDOMNode, xmlDSN As IXMLDOMNode, xmlExportOptions As IXMLDOMNode
        Dim xmlTablePrefix As IXMLDOMNode, xmlExcludeDynamicAccts As IXMLDOMNode

        initFromXML = False

        If xmlNode Is Nothing Then Exit Function

        xmlOptions = xmlNode.selectSingleNode("//" & EA_OPTIONS)

        If xmlOptions Is Nothing Then Exit Function

        xmlDSN = xmlOptions.selectSingleNode("//" & EA_SELECTED_DSN)
        If (Not xmlDSN Is Nothing) Then
            SelectedDSN = xmlDSN.text
        End If

        xmlExportOptions = xmlOptions.selectSingleNode("//" & EA_EXPORT_OPTION)
        If (Not xmlExportOptions Is Nothing) Then
            ExportOption = CLng(xmlExportOptions.text)
        End If

        xmlTablePrefix = xmlOptions.selectSingleNode("//" & EA_TABLE_PREFIX)
        If (Not xmlTablePrefix Is Nothing) Then
            TablePrefix = xmlTablePrefix.text
        End If

        xmlExcludeDynamicAccts = xmlOptions.selectSingleNode("//" & EA_EXCLUDE_DYN_ACCTS)
        If (Not xmlExcludeDynamicAccts Is Nothing) Then
            ExcludeDynamicAccts = CBool(xmlExcludeDynamicAccts.text)
        End If

        initFromXML = True
    End Function
End Class

